package component.security.encrypt;

import java.security.*;

/**
 * 数字签名类
 */

public class Signing {
  public Signing() {
  }

  // 签名算法表
  public final static String SHA1_RSA = "SHA1withRSA";
  public final static String MD5_RSA = "MD5withRSA";
  public final static String DSA = "DSA";

  /**
   * 对信息用私钥签名并返回签名信息
   * @param message 要进行签名的字节数组
   * @param algorithm 签名算法(RSA公开加密算法可以使用SHA1withRSA或者MD5withRSA)
   * @param prikey 私钥密钥
   * @return 签名字节数组
   * @throws NoSuchAlgorithmException 指定的签名算法不被支持
   * @throws InvalidKeyException 指定的私有密钥不正确
   * @throws SignatureException 进行签名时出错
   */
  public static byte[] getSignature(byte[] message, String algorithm,
                             PrivateKey prikey) throws NoSuchAlgorithmException,
      InvalidKeyException, SignatureException {
    if (prikey == null || message == null) {
      return null;
    }
    Signature signat = Signature.getInstance(algorithm != null ? algorithm :
                                             prikey.getAlgorithm());
    signat.initSign(prikey);
    signat.update(message);
    byte[] signed = signat.sign();
    return signed;
  }

  /**
   * <p>根据公钥验证信息和签名</p>
   * 注意产生签名的算法和验证时使用的算法要保持一致
   * @param message 产生签名的原字节数组信息
   * @param algorithm 签名算法(RSA公开加密算法可以使用SHA1withRSA或者MD5withRSA)
   * @param signature 对原信息产生的签名字节数组
   * @param pubkey 签名所使用的私钥对应的公钥
   * @return 验证结果; true=验证正确,false=验证错误
   * @throws NoSuchAlgorithmException 指定算法不被支持
   * @throws InvalidKeyException 指定的公钥有误
   * @throws SignatureException 验证签名出错
   */
  public static boolean verifySignedMessage(byte[] message, String algorithm,
                                     byte[] signature, PublicKey pubkey) throws
      NoSuchAlgorithmException, InvalidKeyException, SignatureException {
    Signature signatcheck = Signature.getInstance(algorithm != null ? algorithm :
                                                  pubkey.getAlgorithm());
    signatcheck.initVerify(pubkey);
    signatcheck.update(message);
    return signatcheck.verify(signature);
  }

}